package moviedownloader5;

import com.mycompany.moviedownloader.DbModel.Genre;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.mycompany.moviedownloader.DbModel.Movie;
import com.mycompany.moviedownloader.DbModel.Person;
import com.mycompany.moviedownloader.DbModel.Title;
import java.sql.Connection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.DataSource;
import org.apache.commons.dbutils.DbUtils;

public class MovieToDatabase implements AutoCloseable {

    private final DataSource ds;
    private long batch;
    private final long batchSize = 5000;
    private final Connection conn;

    public MovieToDatabase(DataSource ds) {
        Objects.requireNonNull(ds);
        this.ds = ds;
        batch = 0;
        try {
            conn = ds.getConnection();
            conn.setAutoCommit(true);
        } catch (SQLException ex) {
            throw new IllegalArgumentException(ex);
        }
    }
    
    private static boolean isNotNull(Object o){
        return o != null;
    }
    
    private boolean isValid(Movie movie){
        boolean result= isNotNull(movie) &&
                isNotNull(movie.getCast()) &&
                isNotNull(movie.getCsfdId()) &&
                isNotNull(movie.getGenres()) && 
                isNotNull(movie.getMovieFormat()) && 
                isNotNull(movie.getNames());
        
        for (Person person : movie.getCast()) {
            result = result && isNotNull(person);
        }
        
        for (Genre genre : movie.getGenres()) {
            result = result && isNotNull(genre);
        }
        
        for (Title title : movie.getNames()) {
            result = result && isNotNull(title);
        }
        
       return result;
        
    }

    public void insert(Movie movie) {
        if(!isValid(movie)){
            Logger.getLogger(MovieDownloader5.class.getName()).log(Level.SEVERE, "invalid movie passed, movie:"+movie);
            return;
        }
        PreparedStatement prepStm = null;
        try {

            //======================================================
            String filmy_stmnt = "INSERT INTO filmy("
                    + "film_id, rating, krajina_povodu, rok_vydania, trvanie, format_id)"
                    + " VALUES(?, ?, ?, ?, ?, ?)";

            prepStm = conn.prepareStatement(filmy_stmnt,PreparedStatement.RETURN_GENERATED_KEYS);

            prepStm.setInt(1, movie.getCsfdId());
            prepStm.setInt(2, movie.getRating());
            prepStm.setString(3, movie.getOrigin().getCountry());
            prepStm.setInt(4, movie.getOrigin().getReleaseYear());
            prepStm.setInt(5, movie.getOrigin().getDuration());
            prepStm.setInt(6, movie.getMovieFormat().getValue());
            prepStm.executeUpdate();

            //======================================================
            String filmy_zanre_stmnt = "INSERT INTO filmy_zanre("
                    + "film_id, zaner_id)"
                    + " VALUES(?, ?)";

            prepStm = conn.prepareStatement(filmy_zanre_stmnt);

            for (Genre genre : movie.getGenres()) {
                prepStm.setInt(1, movie.getCsfdId());
                prepStm.setInt(2, genre.getValue());
                prepStm.executeUpdate();
            }

            //======================================================
            String nazvy_filmov_stmnt = "INSERT INTO nazvy_filmov("
                    + "nazov, film_id)"
                    + " VALUES(?, ?)";

            prepStm = conn.prepareStatement(nazvy_filmov_stmnt);

            for (Title title : movie.getNames()) {
                prepStm.setString(1, title.getName());
                prepStm.setInt(2, movie.getCsfdId());
                prepStm.executeUpdate();
            }

            //======================================================
            String obsadenie_stmnt = "INSERT INTO obsadenie("
                    + "herec_id, film_id)"
                    + " VALUES(?, ?)";

            prepStm = conn.prepareStatement(obsadenie_stmnt);

            for (Person person : movie.getCast()) {
                prepStm.setInt(1, person.getCsfdId());
                prepStm.setInt(2, movie.getCsfdId());
                prepStm.executeUpdate();
            }

            //======================================================
            if (++batch > batchSize) {
                batch = 0;
              //  conn.commit();
            }
        } catch (SQLException ex) {
            Logger.getLogger(MovieToDatabase.class.getName()).log(Level.SEVERE, null, ex);
        } 
    }

    public void insertCast(Set<Person> cast) {
        String herci_stmnt = "INSERT INTO herci("
                + "herec_id, meno)"
                + " VALUES(?, ?)";
        PreparedStatement prepStm = null;

        try {
            

            for (Person person : cast) {
                prepStm = conn.prepareStatement(herci_stmnt);
                prepStm.setInt(1, person.getCsfdId());
                prepStm.setString(2, person.getName());
                prepStm.executeUpdate();
            }
        } catch (SQLException ex) {
            Logger.getLogger(MovieToDatabase.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    @Override
    public void close() {

        if (conn != null) {
          /*  try {
               conn.commit();
            } catch (SQLException ex) {
                Logger.getLogger(MovieToDatabase.class.getName()).log(Level.SEVERE, null, ex);
            }*/
            DbUtils.closeQuietly(conn);
        }

    }

}
